#include "header/pyramid_stargate.h"

#define N 50

Real32 iris_mesh_init[N][N];

Pnt3f geometry[N][N];

NodePtr createStargateModel()
{

	Matrix m;

// initialize depth mesh

	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++)
			iris_mesh_init[i][j] = 0;

// define quad rings

	GeoPTypesPtr type = GeoPTypesUI8::create();
	beginEditCP(type, GeoPTypesUI8::GeoPropDataFieldMask);
	for (int i=0;i<=20;i++)
		type->addValue(GL_QUADS);
	endEditCP(type, GeoPTypesUI8::GeoPropDataFieldMask);

	GeoPLengthsPtr length = GeoPLengthsUI32::create();
	beginEditCP(length, GeoPLengthsUI32::GeoPropDataFieldMask);
	for (int i=0;i<=20;i++)
		length->addValue(36*4);
	endEditCP(length, GeoPLengthsUI32::GeoPropDataFieldMask);

// define quad ring vertices

	GeoPositions3fPtr pos = GeoPositions3f::create();
	beginEditCP(pos, GeoPositions3f::GeoPropDataFieldMask);
	for (int ring = 0; ring <= 20; ring+=1)
	{
		for (int position = 0; position < 360; position+=10)
		{
			pos->addValue(Pnt3f(2*ring*cos(deg2rad(position)), 2*ring*sin(deg2rad(position)) , 2*iris_mesh_init[ring][position]));
		}
	}
	endEditCP(pos, GeoPositions3f::GeoPropDataFieldMask);

// color only for fallback (mat now)

	GeoColors3fPtr colors = GeoColors3f::create();
	beginEditCP(colors, GeoColors3f::GeoPropDataFieldMask);
	for (int x = 0; x < N; x++)
		for (int z = 0; z < N; z++)
			colors->addValue(Color3f(0,0,(x+1)/(z+1)));
	endEditCP(colors, GeoColors3f::GeoPropDataFieldMask);

// initial normals

	GeoNormals3fPtr norms = GeoNormals3f::create();
	beginEditCP(norms, GeoNormals3f::GeoPropDataFieldMask);
	for (int x = 0; x < N; x++)
		for (int z = 0; z < N; z++)
			norms->addValue(Vec3f(0,1,0));
	endEditCP(norms, GeoNormals3f::GeoPropDataFieldMask);

	SimpleMaterialPtr mat = SimpleMaterial::create();

// simple Material

	beginEditCP(mat);
	mat->setDiffuse(Color3f(0,0,1));
	mat->setSpecular(Color3f(0,1,1));
	mat->setTransparency(0.5);
	endEditCP(mat);

// generate circular quad rings

	GeoIndicesUI32Ptr indices = GeoIndicesUI32::create();
	beginEditCP(indices, GeoIndicesUI32::GeoPropDataFieldMask);
	for (int ring = 0; ring <=20 ; ring++)
	{
		for (int position = 0; position < 35; position++){
			indices->addValue(ring*36+position);       
			indices->addValue((ring+1)*36+position);
			indices->addValue((ring+1)*36+position+1);
			indices->addValue(ring*36+position+1);
		}
		//close ring
		indices->addValue(ring*36+35);       
		indices->addValue((ring+1)*36+35);
		indices->addValue((ring+1)*36+0);
		indices->addValue(ring*36+0);
	}
	endEditCP(indices, GeoIndicesUI32::GeoPropDataFieldMask);

// group our geometry

	GeometryPtr geo = Geometry::create();
	beginEditCP(geo,Geometry::TypesFieldMask|Geometry::LengthsFieldMask|Geometry::IndicesFieldMask|Geometry::PositionsFieldMask|Geometry::NormalsFieldMask|Geometry::ColorsFieldMask);
	geo->setTypes(type);
	geo->setLengths(length);
	geo->setIndices(indices);
	geo->setPositions(pos);
	geo->setNormals(norms);
	geo->setMaterial(mat);
	endEditCP(geo,Geometry::TypesFieldMask|Geometry::LengthsFieldMask|Geometry::IndicesFieldMask|Geometry::PositionsFieldMask|Geometry::NormalsFieldMask|Geometry::ColorsFieldMask);

	NodePtr stargate_iris = Node::create();

	beginEditCP(stargate_iris);
	stargate_iris->setCore(geo);
	endEditCP(stargate_iris);

	setName(stargate_iris,"stargate_iris");

	TransformPtr tsg = Transform::create();
	beginEditCP(tsg, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setTranslate(130, 50, 80);
	tsg->setMatrix(m);
	endEditCP(tsg, Transform::MatrixFieldMask);

	NodePtr stargate_iris_Trans = Node::create();

	beginEditCP(stargate_iris_Trans);
	stargate_iris_Trans->setCore(tsg);
	stargate_iris_Trans->addChild(stargate_iris);
	endEditCP(stargate_iris_Trans);

	// load stargate ring

	cout << "--> parsing external object: stargate.wrl" << endl;
	NodePtr external_sg_construct = SceneFileHandler::the().read("external_objects/stargate.wrl");

	TransformPtr tsgc = Transform::create();
	beginEditCP(tsgc, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setScale(16);
	m.setTranslate(130, 50, 80);
	tsgc->setMatrix(m);
	endEditCP(tsgc, Transform::MatrixFieldMask);

	NodePtr stargate_construct_Trans = Node::create();

	beginEditCP(stargate_construct_Trans);
	stargate_construct_Trans->setCore(tsgc);
	stargate_construct_Trans->addChild(external_sg_construct);
	endEditCP(stargate_construct_Trans);

	// load stargate socket

	cout << "--> parsing external object: stargate_socket.wrl" << endl;
	NodePtr external_sg_socket = SceneFileHandler::the().read("external_objects/stargate_socket.wrl");

	TransformPtr tsgs = Transform::create();
	beginEditCP(tsgs, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setScale(10);
	m.setTranslate(130, 0, 80);
	tsgs->setMatrix(m);
	endEditCP(tsgs, Transform::MatrixFieldMask);

	TransformPtr tsgs_r = Transform::create();
	beginEditCP(tsgs_r, Transform::MatrixFieldMask);
	m.setIdentity();
	m.setRotate(Quaternion(Vec3f(0,1,0), +3.14159));
	tsgs_r->setMatrix(m);
	endEditCP(tsgs_r, Transform::MatrixFieldMask);

	NodePtr stargate_socket_Rot = Node::create();

	beginEditCP(stargate_socket_Rot);
	stargate_socket_Rot->setCore(tsgs_r);
	stargate_socket_Rot->addChild(external_sg_socket);
	endEditCP(stargate_socket_Rot);

	NodePtr stargate_socket_Trans = Node::create();

	beginEditCP(stargate_socket_Trans);
	stargate_socket_Trans->setCore(tsgs);
	stargate_socket_Trans->addChild(stargate_socket_Rot);
	endEditCP(stargate_socket_Trans);

	NodePtr stargate = Node::create();

	beginEditCP(stargate);
	stargate->setCore(Group::create());
	stargate->addChild(stargate_construct_Trans);
	stargate->addChild(stargate_socket_Trans);
	stargate->addChild(stargate_iris_Trans);
	endEditCP(stargate);

	return stargate;
}
